package com.platform.web.controller.module;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.platform.common.annotation.Log;
import com.platform.common.core.controller.BaseController;
import com.platform.common.core.domain.AjaxResult;
import com.platform.common.core.domain.Ztree;
import com.platform.common.core.page.TableDataInfo;
import com.platform.common.core.text.Convert;
import com.platform.common.enums.BusinessType;
import com.platform.common.utils.StringUtils;
import com.platform.common.utils.netty.ChannelSupervise;
import com.platform.common.utils.netty.NettyUtil;
import com.platform.common.utils.poi.ExcelUtil;
import com.platform.common.utils.redis.RedisRun;
import com.platform.common.utils.redis.RedisUtil;
import com.platform.framework.util.ShiroUtils;
import com.platform.module.domain.*;
import com.platform.module.service.*;
import com.platform.system.service.ISysDictDataService;
import io.netty.channel.Channel;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 集中器设备数据Controller
 *
 * @author wangqi
 * @date 2020-07-13
 */
@Controller
@RequestMapping("/module/concentrator/data")
public class BaseConcentratorDataController extends BaseController
{
    private String prefix = "module/concentrator/data";

    @Autowired
    private IBaseConcentratorDataService baseConcentratorDataService;

    @Autowired
    private IBaseConcentratorTypeService baseConcentratorTypeService;

    @Autowired
    private IBaseCalorimeterDataService calorimeterDataService;

    @Autowired
    private IBaseValveDataService valveDataService;

    @Autowired
    private ILinkConcentratorValveService linkConcentratorValveService;

    @Autowired
    private ILinkConcentratorMeterService linkConcentratorMeterService;
    @Autowired
    private ISysDictDataService sysDictDataService;

    @Autowired
    private RedisUtil redisUtil;


    @RequiresPermissions("module:concentrator:data:view")
    @GetMapping("/{typeId}")
    public String data(@PathVariable("typeId") Long typeId, ModelMap mmap)
    {
        BaseConcentratorType baseConcentratorType = new BaseConcentratorType();
        if(typeId != 0L){
            baseConcentratorType = baseConcentratorTypeService.getById(typeId);
        }
        mmap.put("type", baseConcentratorType);
        mmap.put("concentratorList", baseConcentratorTypeService.list());
        return prefix + "/data";
    }

    /**
     * 查询集中器设备数据列表
     */
    @RequiresPermissions("module:concentrator:data:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(BaseConcentratorData baseConcentratorData)
    {
        startPage();
        List<BaseConcentratorData> list = baseConcentratorDataService.selectBaseConcentratorDataList(baseConcentratorData);
        return getDataTable(list);
    }

    /**
     * 导出集中器设备数据列表
     */
    @RequiresPermissions("module:concentrator:data:export")
    @Log(title = "集中器设备数据", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(BaseConcentratorData baseConcentratorData)
    {
        List<BaseConcentratorData> list = baseConcentratorDataService.selectBaseConcentratorDataList(baseConcentratorData);
        ExcelUtil<BaseConcentratorData> util = new ExcelUtil<BaseConcentratorData>(BaseConcentratorData.class);
        for(BaseConcentratorData data : list){
            String status = sysDictDataService.selectDictLabel("equipment_status", data.getStatus());
            data.setStatus(status);
        }
        return util.exportExcel(list, "集中器资料");
    }

    /**
     * @Author 王琦
     * @Description //阀门型号信息导入
     * @Date 2020/6/19 19:56
     * @Param [file, updateSupport]
     * @return com.platform.common.core.domain.AjaxResult
     */
    @Log(title = "集中器数据导入", businessType = BusinessType.IMPORT)
    @RequiresPermissions("module:concentrator:data:import")
    @PostMapping("/importData")
    @ResponseBody
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<BaseConcentratorData> util = new ExcelUtil<BaseConcentratorData>(BaseConcentratorData.class);
        List<BaseConcentratorData> concentratorDataList = util.importExcel(file.getInputStream());
        String operName = ShiroUtils.getSysUser().getLoginName();
        String message = baseConcentratorDataService.importBaseConcentratorData(concentratorDataList, updateSupport, operName);
        return AjaxResult.success(message);
    }

    /**
     * @Author 王琦
     * @Description //导入模板
     * @Date 2020/6/19 19:56
     * @Param []
     * @return com.platform.common.core.domain.AjaxResult
     */
    @GetMapping("/importTemplate")
    @ResponseBody
    public AjaxResult importTemplate()
    {
        ExcelUtil<BaseConcentratorData> util = new ExcelUtil<BaseConcentratorData>(BaseConcentratorData.class);
        return util.importTemplateExcel("集中器信息");
    }


    /**
     * 新增集中器设备数据
     */
    @GetMapping("/add/{typeId}")
    public String add(@PathVariable("typeId") Long typeId, ModelMap mmap)
    {
        List<BaseConcentratorType> concentratorList = baseConcentratorTypeService.list();
        mmap.put("concentratorList", concentratorList);
        mmap.put("typeId", typeId);
        return prefix + "/add";
    }

    /**
     * 新增保存集中器设备数据
     */
    @RequiresPermissions("module:concentrator:data:add")
    @Log(title = "集中器设备数据", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(BaseConcentratorData baseConcentratorData)
    {
        baseConcentratorData.setCreateBy(ShiroUtils.getLoginName());
        return toAjax(baseConcentratorDataService.insertBaseConcentratorData(baseConcentratorData));
    }

    /**
     * 修改集中器设备数据
     */
    @GetMapping("/edit/{concentratorId}")
    public String edit(@PathVariable("concentratorId") String concentratorId, ModelMap mmap)
    {
        BaseConcentratorData baseConcentratorData = baseConcentratorDataService.getById(concentratorId);
        mmap.put("baseConcentratorData", baseConcentratorData);
        List<BaseConcentratorType> concentratorList = baseConcentratorTypeService.list();
        mmap.put("concentratorList", concentratorList);
        return prefix + "/edit";
    }

    /**
     * 修改保存集中器设备数据
     */
    @RequiresPermissions("module:concentrator:data:edit")
    @Log(title = "集中器设备数据", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(BaseConcentratorData baseConcentratorData)
    {
        baseConcentratorData.setUpdateBy(ShiroUtils.getLoginName());
        return toAjax(baseConcentratorDataService.updateBaseConcentratorData(baseConcentratorData));
    }

    /**
     * 删除集中器设备数据
     */
    @RequiresPermissions("module:concentrator:data:remove")
    @Log(title = "集中器设备数据", businessType = BusinessType.DELETE)
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        return toAjax(baseConcentratorDataService.deleteBaseConcentratorDataByIds(ids));
    }


    /**
     * 分配热表
     */
    @RequiresPermissions("module:concentrator:data:edit")
    @GetMapping("/authMeter/{concentratorId}")
    public String authMeter(@PathVariable("concentratorId") String concentratorId, ModelMap mmap)
    {
        mmap.put("concentratorId", concentratorId);
        return prefix + "/authMeter";
    }

    /**
     * 查询已分配热表角色列表
     */
    @RequiresPermissions("module:concentrator:data:list")
    @PostMapping("/authMeter/allocatedList")
    @ResponseBody
    public TableDataInfo allocatedList(BaseCalorimeterData calorimeter)
    {
        startPage();
        List<BaseCalorimeterData> list = calorimeterDataService.selectAllocatedList(calorimeter);
        return getDataTable(list);
    }

    /**
     * 取消授权
     */
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PostMapping("/authMeter/cancel")
    @ResponseBody
    public AjaxResult cancelAuthMeter(LinkConcentratorMeter concentratorMeter)
    {
        return toAjax(baseConcentratorDataService.deleteAuthMeter(concentratorMeter));
    }

    /**
     * 批量取消授权
     */
    @Log(title = "集中器管理", businessType = BusinessType.GRANT)
    @PostMapping("/authMeter/cancelAll")
    @ResponseBody
    public AjaxResult cancelAuthMeterAll(String concentratorId, String calorimeterIds)
    {
        return toAjax(baseConcentratorDataService.deleteAuthMeters(concentratorId, calorimeterIds));
    }

    /**
     * 选择热表
     */
    @GetMapping("/authMeter/selectMeter/{concentratorId}")
    public String selectMeter(@PathVariable("concentratorId") String concentratorId, ModelMap mmap)
    {
        mmap.put("concentratorId", concentratorId);
        return prefix + "/selectMeter";
    }

    /**
     * 查询未分配热表列表
     */
    @RequiresPermissions("module:concentrator:data:list")
    @PostMapping("/authMeter/unallocatedList")
    @ResponseBody
    public TableDataInfo unallocatedList(BaseCalorimeterData baseCalorimeterData)
    {
        startPage();
        List<BaseCalorimeterData> list = calorimeterDataService.selectUnallocatedList(baseCalorimeterData);
        return getDataTable(list);
    }

    /**
     * 批量选择热表授权
     */
    @Log(title = "集中器管理", businessType = BusinessType.GRANT)
    @PostMapping("/authMeter/selectAll")
    @ResponseBody
    public AjaxResult selectAuthMeterAll(String concentratorId, String calorimeterIds)
    {
        return toAjax(baseConcentratorDataService.insertAuthMeters(concentratorId, calorimeterIds));
    }

    /**
     * 分配阀门
     */
    @RequiresPermissions("module:concentrator:data:edit")
    @GetMapping("/authValve/{concentratorId}")
    public String authValve(@PathVariable("concentratorId") String concentratorId, ModelMap mmap)
    {
        mmap.put("concentratorId", concentratorId);
        return prefix + "/authValve";
    }

    /**
     * 查询已分配阀门角色列表
     */
    @RequiresPermissions("module:concentrator:data:list")
    @PostMapping("/authValve/allocatedList")
    @ResponseBody
    public TableDataInfo allocatedList(BaseValveData valve)
    {
        startPage();
        List<BaseValveData> list = valveDataService.selectAllocatedList(valve);
        return getDataTable(list);
    }

    /**
     * 取消授权
     */
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PostMapping("/authValve/cancel")
    @ResponseBody
    public AjaxResult cancelAuthValve(LinkConcentratorValve concentratorValve)
    {
        return toAjax(baseConcentratorDataService.deleteAuthValve(concentratorValve));
    }

    /**
     * 批量取消授权
     */
    @Log(title = "集中器管理", businessType = BusinessType.GRANT)
    @PostMapping("/authValve/cancelAll")
    @ResponseBody
    public AjaxResult cancelAuthValveAll(String concentratorId, String valveIds)
    {
        return toAjax(baseConcentratorDataService.deleteAuthValves(concentratorId, valveIds));
    }

    /**
     * 选择阀门
     */
    @GetMapping("/authValve/selectValve/{concentratorId}")
    public String selectValve(@PathVariable("concentratorId") String concentratorId, ModelMap mmap)
    {
        mmap.put("concentratorId", concentratorId);
        return prefix + "/selectValve";
    }

    /**
     * 查询未分配阀门列表
     */
    @RequiresPermissions("module:concentrator:data:list")
    @PostMapping("/authValve/unallocatedList")
    @ResponseBody
    public TableDataInfo unallocatedList(BaseValveData baseValveData)
    {
        startPage();
        List<BaseValveData> list = valveDataService.selectUnallocatedList(baseValveData);
        return getDataTable(list);
    }

    /**
     * 批量选择阀门授权
     */
    @Log(title = "集中器管理", businessType = BusinessType.GRANT)
    @PostMapping("/authValve/selectAll")
    @ResponseBody
    public AjaxResult selectAuthValveAll(String concentratorId, String valveIds)
    {
        return toAjax(baseConcentratorDataService.insertAuthValves(concentratorId, valveIds));
    }

    /**
     * 采集器初始化
     */
    @Log(title = "采集器初始化", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:initialize")
    @PostMapping("/initialize")
    @ResponseBody
    public AjaxResult initialize(String concentratorIds) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "0A";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"采集器初始化");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"初始化失败");
            }else{
                List<LinkConcentratorMeter> concentratorMeters = linkConcentratorMeterService.list(new QueryWrapper<LinkConcentratorMeter>().eq("concentrator_id",concentratorId));
                for(LinkConcentratorMeter linkConcentratorMeter : concentratorMeters){
                    linkConcentratorMeter.setStatus("0");
                    linkConcentratorMeterService.updateLinkConcentratorMeter(linkConcentratorMeter);
                }
                List<LinkConcentratorValve> concentratorValves = linkConcentratorValveService.list(new QueryWrapper<LinkConcentratorValve>().eq("concentrator_id",concentratorId));
                for(LinkConcentratorValve linkConcentratorValve : concentratorValves){
                    linkConcentratorValve.setStatus("0");
                    linkConcentratorValveService.updateLinkConcentratorValve(linkConcentratorValve);
                }
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 批量设置采集器心跳时间
     */
    @GetMapping("/heart/{concentratorIds}")
    public String heart(@PathVariable("concentratorIds") String concentratorIds, ModelMap mmap)
    {
        mmap.put("concentratorIds",concentratorIds);
        return prefix + "/heart";
    }

    /**
     * 批量设置采集器心跳时间
     */
    @Log(title = "批量设置采集器心跳时间", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:heart")
    @PostMapping("/heart")
    @ResponseBody
    public AjaxResult heart(BaseConcentratorData concentratorData) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorData.getConcentratorIds()));
        String hex = NettyUtil.get16HexNum(concentratorData.getHeart());
        if(hex.length()<2){
            hex = "0"+hex;
        }
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "08";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(hex);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " " + hex + " 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"批量设置采集器心跳时间");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"设置心跳时间失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 批量设置采集器离线采集时间
     */
    @GetMapping("/settime/{concentratorIds}")
    public String settime(@PathVariable("concentratorIds") String concentratorIds, ModelMap mmap)
    {
        mmap.put("concentratorIds",concentratorIds);
        return prefix + "/settime";
    }

    /**
     * 批量设置采集器离线采集时间
     */
    @Log(title = "批量设置采集器离线采集时间", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:settime")
    @PostMapping("/settime")
    @ResponseBody
    public AjaxResult settime(BaseConcentratorData concentratorData) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorData.getConcentratorIds()));
        String hex = concentratorData.getSettime().toString();
        if(hex.length()<2){
            hex = "0"+hex;
        }
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);
            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "07";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(hex);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " " + hex + " 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"批量设置采集器离线采集时间");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"设置采集器离线采集时间失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 批量设置阀门开度
     */
    @GetMapping("/aperture/{concentratorIds}")
    public String aperture(@PathVariable("concentratorIds") String concentratorIds, ModelMap mmap)
    {
        mmap.put("concentratorIds",concentratorIds);
        return prefix + "/aperture";
    }

    /**
     * 批量设置阀门开度
     */
    @Log(title = "批量设置阀门开度", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:aperture")
    @PostMapping("/aperture")
    @ResponseBody
    public AjaxResult aperture(BaseConcentratorData concentratorData) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorData.getConcentratorIds()));
        String hex = NettyUtil.get16HexNum(concentratorData.getAperture());
        if(hex.length()<2){
            hex = "0"+hex;
        }
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);
            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "06";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(hex);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " " + hex + " 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"批量设置阀门开度");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"设置阀门开度失败");
            }else{
                List<LinkConcentratorValve> list = linkConcentratorValveService.list(new QueryWrapper<LinkConcentratorValve>().eq("concentrator_id", concentratorId));
                for(LinkConcentratorValve linkConcentratorValve : list){
                    String valveId = linkConcentratorValve.getValveId();
                    BaseValveData baseValveData = valveDataService.getById(valveId);
                    baseValveData.setAperture(concentratorData.getAperture());
                    valveDataService.updateBaseValveData(baseValveData);
                }
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 获取所有已登记的设备
     */
    @Log(title = "获取所有已登记的设备", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:select")
    @PostMapping("/select")
    @ResponseBody
    public AjaxResult select(String concentratorIds) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);
            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "0C";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA "+ cenlow +" "+ cenhigh + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr, channel, "获取所有已登记的设备");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(result==null || result.equals("") || result.equals("0")){
                failureMsg.append("<br/>采集器"+concentratorId+"没有登记的设备");
            }else{
                return AjaxResult.success("采集器"+concentratorId+"有"+result+"个登记设备");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 采集器批量读取数据
     */
    @Log(title = "采集器批量读取数据", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:check")
    @PostMapping("/check")
    @ResponseBody
    public AjaxResult check(String concentratorIds) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "05";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA "+ cenlow +" "+ cenhigh + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"全部设备信息采集");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"获取所有设备的采集信息失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 批量设置采集器心跳时间
     */
    @GetMapping("/change/{concentratorIds}")
    public String change(@PathVariable("concentratorIds") String concentratorIds, ModelMap mmap)
    {
        mmap.put("concentratorIds",concentratorIds);
        return prefix + "/change";
    }

    /**
     * 批量设置服务器地址
     */
    @Log(title = "批量设置服务器地址", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:change")
    @PostMapping("/change")
    @ResponseBody
    public AjaxResult change(BaseConcentratorData concentratorData) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorData.getConcentratorIds()));
        String serverip = concentratorData.getServerip();
        String[] ips = new String[4];
        for(int i=0;i<4;i++){
            String s = StringUtils.substringBefore(serverip,".");
            ips[i]= NettyUtil.get16HexNum(Integer.parseInt(s));
            serverip =  StringUtils.substringAfter(serverip, ".");
        }
        String serverport = NettyUtil.get16HexNum(concentratorData.getServerport());
        if(serverport.length()<4){
            serverport = String.format("%04d", serverport);
        }
        String p1 = serverport.substring(0,2);
        String p2 = serverport.substring(2,4);
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }
            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);
            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"已离线，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "13";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont)
                    +NettyUtil.get10HexNum(ips[0])+NettyUtil.get10HexNum(ips[1])+NettyUtil.get10HexNum(ips[2])+NettyUtil.get10HexNum(ips[3])
                    +NettyUtil.get10HexNum(p1)+NettyUtil.get10HexNum(p2);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA " + cenlow + " " + cenhigh + " 00 00 00 00 " + cont + " " + ips[0] + " " + ips[1] + " " + ips[2] + " " + ips[3] + " " + p1 + " " + p2 + " " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"批量设置服务器ip地址");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"批量设置服务器ip地址失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 查询采集器时间
     */
    @Log(title = "查询采集器时间", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:collect")
    @PostMapping("/collect")
    @ResponseBody
    public AjaxResult collect(String concentratorIds) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "0D";
            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }
            String response = "AA "+ cenlow +" "+ cenhigh + " 00 00 00 00 " + cont + " 00 00 00 00 00 00 " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"查询采集器时间");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(result==null || result.equals("") || result.equals("0")){
                failureMsg.append("<br/>采集器"+concentratorId+"查询时间失败");
            }else{
                return AjaxResult.success("当前采集器时间为："+result);
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 校准采集器时间
     */
    @Log(title = "校准采集器时间", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:correct")
    @PostMapping("/correct")
    @ResponseBody
    public AjaxResult correct(String concentratorIds) throws Exception {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorIds));
        StringBuilder failureMsg = new StringBuilder();
        for(String concentratorId : ids){
            boolean status = redisUtil.hHasKey("sys-netty", concentratorId);
            if(!status){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //获取采集器高位
            String cenhigh = concentratorId.substring(0,2);
            //获取采集器低位
            String cenlow = concentratorId.substring(2,4);

            //获取通道id
            String channelId = redisUtil.hget("sys-netty",cenhigh+cenlow).toString();
            Channel channel = ChannelSupervise.findChannel(channelId);
            if(channel==null){
                failureMsg.append("采集器"+concentratorId+"通道未开启，请联系现场维护人员重启采集器");
                break;
            }

            //控制码
            String cont = "0B";

            Calendar date = Calendar.getInstance();
            String year = String.valueOf(date.get(Calendar.YEAR));
            String month = String.valueOf(date.get(Calendar.MONTH)+1);
            if(month.length()<2){
                month = "0"+month;
            }
            String day = String.valueOf(date.get(Calendar.DATE));
            if(day.length()<2){
                day = "0"+day;
            }
            String hour = String.valueOf(date.get(Calendar.HOUR_OF_DAY));
            if(hour.length()<2){
                hour = "0"+hour;
            }
            String minute = String.valueOf(date.get(Calendar.MINUTE));
            if(minute.length()<2){
                minute = "0"+minute;
            }
            String second = String.valueOf(date.get(Calendar.SECOND));
            if(second.length()<2){
                second = "0"+second;
            }

            //计算校验码
            int ll = NettyUtil.get10HexNum(cenhigh)+NettyUtil.get10HexNum(cenlow)+NettyUtil.get10HexNum(cont)+NettyUtil.get10HexNum(year)+NettyUtil.get10HexNum(month)+NettyUtil.get10HexNum(day)+NettyUtil.get10HexNum(hour)+NettyUtil.get10HexNum(minute)+NettyUtil.get10HexNum(second);
            String check = NettyUtil.get16HexNum(ll);
            if(check.length()<2){
                check = "0" + check;
            }else{
                check = check.substring(check.length()-2);
            }

            String response = "AA "+ cenlow +" "+ cenhigh + " 00 00 00 00 " + cont + " " + year.substring(2) + " " + month + " " + day + " " + hour + " " + minute + " " + second + " " + check + " FF ";
            String revertStr = response.replace(" ", "");
            NettyUtil.writeToClient(revertStr,channel,"校准采集器时间");
            CountDownLatch countDownLatch = new CountDownLatch(1);
            new Thread(new RedisRun(countDownLatch,redisUtil,concentratorId,cont)).start();
            countDownLatch.await();
            String result = RedisRun.result;
            if(!result.equals("00")){
                failureMsg.append("<br/>采集器"+concentratorId+"校准时间失败");
            }
        }
        if(failureMsg.toString().equals("")){
            return AjaxResult.success();
        }else{
            return AjaxResult.error(failureMsg.toString());
        }
    }

    /**
     * 消除采集器MBUS告警提示
     */
    @Log(title = "消除采集器MBUS告警提示", businessType = BusinessType.GRANT)
    @RequiresPermissions("module:concentrator:data:dispel")
    @PostMapping("/dispel")
    @ResponseBody
    public AjaxResult dispel(String concentratorIds) {
        List<String> ids = Arrays.asList(Convert.toStrArray(concentratorIds));
        for(String concentratorId : ids) {
            redisUtil.hdel(concentratorId, "0F");
        }
        return success();
    }

    /**
     * 校验采集器代码
     */
    @PostMapping("/checkConcentratorDataCodeUnique")
    @ResponseBody
    public String checkConcentratorDataCodeUnique(BaseConcentratorData baseConcentratorData)
    {
        return baseConcentratorDataService.checkConcentratorDataCodeUnique(baseConcentratorData);
    }

    /**
     * 加载采集器数列表
     */
    @GetMapping("/treeData")
    @ResponseBody
    public List<Ztree> treeData()
    {
        List<Ztree> ztrees = baseConcentratorDataService.selectConcentratorTree();
        return ztrees;
    }

}
